
static uint8_t idle_check(void)
{
    if (ComObj.snd_st != COM_TX_IDLE)
        return 0;
    if (ComObj.rcv_st != COM_RX_IDLE)
        return 0;
    return 1;
}

static int16_t wait_for_idle(uint16_t time_out)
{

    time_out /= 10;

    while(time_out --)
    {
        if(!idle_check())
        {
            com_ext_wait(10);
        }
        else
        {
            break;
        }
    }

    return time_out;
}

static void rcv_st_clr(void)
{
    ComObj.index_rx_rcv = 0;
    ComObj.index_rx_get = 0;
    ComObj.St.bits.err_hal = 0;
    ComObj.master_wait_time_cnt = 0;
    ComObj.b_timer_on = 0;
    ComObj.rcv_end_time_cnt = 0;
    ComObj.rcv_end_keep_cnt = 0;
    ComObj.rcv_squence = 0;

    ComObj.rcv_st = COM_RX_IDLE;
}

static int16_t signal_rcv_data(uint8_t *p_dat, uint16_t buff_size)
{
    int16_t len = buff_size;
    int16_t cnt = 0;

    if(ComObj.St.bits.cycle_mode)
        return 0;

    while(len--)
    {
        if(ComObj.index_rx_get < ComObj.index_rx_rcv)
        {
            *p_dat++ = ComObj.rx_buff[ComObj.index_rx_get++];
            cnt++;
        }
        else
        {
            break;
        }
    }

    return cnt;
}

static int16_t signal_snd_data(uint8_t *p_dat, uint16_t len)
{
    uint8_t send_ok = 0;

    if(ComObj.St.bits.cycle_mode)
        return 1;

    if(wait_for_idle(3000))
    {
        ComObj.dat_mode = COM_DAT_DATA;
        ComObj.p_tx = p_dat;
        ComObj.index_tx_send = 0;
        ComObj.index_tx_fill = len;
        ComObj.snd_st = COM_TX_XMIT;
        com_tx_enbale(1);

        send_ok = 1;
    }

    return send_ok;
}

static int16_t signal_snd_string(uint8_t *p_dat)
{
    uint8_t send_ok = 0;

    if(ComObj.St.bits.cycle_mode)
        return 1;

    if(wait_for_idle(3000))
    {
        ComObj.dat_mode = COM_DAT_STRING;
        ComObj.p_tx = p_dat;
        ComObj.index_tx_send = 0;
        ComObj.index_tx_fill = INT16_MAX;
        ComObj.snd_st = COM_TX_XMIT;
        com_tx_enbale(1);

        send_ok = 1;
    }

    return send_ok;
}

static void cycle_snd_byte(uint8_t ch)
{
    if(!ComObj.St.bits.cycle_mode)
        return;

    ComObj.tx_buff[ComObj.index_tx_fill++] = ch;
    if(ComObj.index_tx_fill >= ComObj.tx_buff_size)
        ComObj.index_tx_fill = 0;
}

static int16_t cycle_rcv_byte(void)
{
    int16_t ch;

    if(!ComObj.St.bits.cycle_mode)
        return COM_DAT_NULL;

    if(ComObj.index_rx_get == ComObj.index_rx_rcv)
        return COM_DAT_NULL;

    ch = ComObj.rx_buff[ComObj.index_rx_get++];

    if(ComObj.index_rx_get >= ComObj.rx_buff_size)
        ComObj.index_rx_get = 0;

    return ch;
}

static void cycle_snd_string(uint8_t * str)
{
    if(!ComObj.St.bits.cycle_mode)
        return;

    while(*str)
    {
        ComObj.tx_buff[ComObj.index_tx_fill++] = *str++;
        if(ComObj.index_tx_fill >= ComObj.tx_buff_size)
            ComObj.index_tx_fill = 0;
    }
}

static void cycle_snd_data(uint8_t * dat, uint16_t len)
{
    if(!ComObj.St.bits.cycle_mode)
        return;

    while(len--)
    {
        ComObj.tx_buff[ComObj.index_tx_fill++] = *dat++;
        if(ComObj.index_tx_fill >= ComObj.tx_buff_size)
            ComObj.index_tx_fill = 0;
    }
}

static uint16_t cycle_rcv_multi(uint8_t * dat, uint16_t buff_size)
{
    uint16_t len = 0;

    if(!ComObj.St.bits.cycle_mode)
        return 0;

    while(ComObj.index_rx_get != ComObj.index_rx_rcv)
    {
        *dat++ = ComObj.rx_buff[ComObj.index_rx_get++];

        if(ComObj.index_rx_get >= ComObj.rx_buff_size)
            ComObj.index_rx_get = 0;
        len ++;

        if(len >= buff_size)
            break;
    }

    return len;
}

static uint16_t cycle_rcv_line(uint8_t * dat)
{
    uint16_t len = 0;
    uint16_t index, size, rcv_site;
    uint8_t b_end_found, ch;

    if(!ComObj.St.bits.cycle_mode)
        return 0;

    index = ComObj.index_rx_get;
    size = ComObj.rx_buff_size;
    rcv_site = ComObj.index_rx_rcv;
    b_end_found = 0;

    while(index != rcv_site)
    {
        ch = ComObj.rx_buff[index++];
        *dat++ = ch;
        len++;

        if(index >= size)
            index = 0;   

        if('\n' == ch)
        {
            b_end_found = 1;
            break;
        }
    }

    if(b_end_found)
    {
        ComObj.index_rx_get = index;
    }
    else
    {
        len = 0;
    }

    *dat++ = 0;

    return len;
}

static uint16_t cycle_rcv_end_4B(uint8_t * dat, uint32_t symbol)
{
    uint16_t len = 0;
    uint16_t index, size, rcv_site;
    uint8_t b_end_found, ch;
    uint32_t snow;

    if(!ComObj.St.bits.cycle_mode)
        return 0;

    index = ComObj.index_rx_get;
    size = ComObj.rx_buff_size;
    rcv_site = ComObj.index_rx_rcv;
    b_end_found = 0;
    snow = 0;

    while(index != rcv_site)
    {
        ch = ComObj.rx_buff[index++];
        *dat++ = ch;
        len++;

        if(index >= size)
            index = 0;   

        snow <<= 8;
        snow |= ch;

        if(symbol == snow)
        {
            b_end_found = 1;
            break;
        }
    }

    if(b_end_found)
    {
        ComObj.index_rx_get = index;
    }
    else
    {
        len = 0;
    }

    *dat++ = 0;

    return len;
}

static uint16_t cycle_rcv_end_2B(uint8_t * dat, uint16_t symbol)
{
    uint16_t len = 0;
    uint16_t index, size, rcv_site;
    uint8_t b_end_found, ch;
    uint16_t snow;

    if(!ComObj.St.bits.cycle_mode)
        return 0;

    index = ComObj.index_rx_get;
    size = ComObj.rx_buff_size;
    rcv_site = ComObj.index_rx_rcv;
    b_end_found = 0;
    snow = 0;

    while(index != rcv_site)
    {
        ch = ComObj.rx_buff[index++];
        *dat++ = ch;
        len++;

        if(index >= size)
            index = 0;   

        snow <<= 8;
        snow |= ch;

        if(symbol == snow)
        {
            b_end_found = 1;
            break;
        }
    }

    if(b_end_found)
    {
        ComObj.index_rx_get = index;
    }
    else
    {
        len = 0;
    }

    *dat++ = 0;

    return len;
}

static uint16_t cycle_rcv_remain_amount(void)
{
    if(ComObj.index_rx_get <= ComObj.index_rx_rcv)
    {
        return (ComObj.index_rx_rcv - ComObj.index_rx_get);
    }
    else
    {
        return (ComObj.index_rx_rcv + ComObj.rx_buff_size - ComObj.index_rx_get);
    }
}

static uint16_t cycle_snd_remain_amount(void)
{
    if(ComObj.index_tx_send <= ComObj.index_tx_fill)
    {
        return (ComObj.index_tx_fill - ComObj.index_tx_send);
    }
    else
    {
        return (ComObj.index_tx_fill + ComObj.tx_buff_size - ComObj.index_tx_send);
    }
}

static const com_fun_type com_fun =
{
    com_rx_enbale,
    com_tx_enbale,
    com_timer_handle,

    idle_check,
    wait_for_idle,
    rcv_st_clr,

    signal_rcv_data,
    signal_snd_data,
    signal_snd_string,

    cycle_snd_byte,
    cycle_rcv_byte,
    cycle_snd_string,
    cycle_snd_data,
    cycle_rcv_multi,
    cycle_rcv_line,
    cycle_rcv_end_4B,
    cycle_rcv_end_2B,
    cycle_rcv_remain_amount,
    cycle_snd_remain_amount,
};

